<template>
  <div class="_count-down">
    <span v-for="(v, i) of views" :class="'item item-' + i" :key="i">{{v}}</span>
  </div>
</template>

<script>
//修复倒计时偏差的倒计时函数
function SetInterval(callback, time) {
  this.start = new Date().getTime();
  this.end;
  this.offset;
  this.loopNum = 0;
  this.timeoutTag = null;
  this.time = time;
  this.callback = callback;
  this.$set(time);
}
SetInterval.prototype.$set = function (_time) {
  var that = this;
  if (this.timeoutTag === undefined) return;
  clearTimeout(this.timeoutTag);
  this.timeoutTag = null;
  that.timeoutTag = setTimeout(function () {
    that.loopNum++;
    that.end = new Date().getTime();
    that.callback();
    that.offset = that.end - that.start - that.time * that.loopNum;
    //console.log("333,,,偏移了" + that.offset);
    if (that.offset > 0) {
      that.$set(that.time - that.offset);
    } else if (that.offset < 0) {
      that.$set(that.time + that.offset);
    } else {
      that.$set(that.time);
    }
  }, _time);
};
SetInterval.prototype.$clear = function () {
  clearTimeout(this.timeoutTag);
  //便于拦截区分，此处必须设置为undefined
  this.timeoutTag = undefined;
};

function checkTime(i) {
  //将0-9的数字前面加上0，例1变为01
  if (i < 10) {
    i = "0" + i;
  }
  return i;
}
var gettime = function(leftTime) {
  var days = checkTime(parseInt(leftTime / 1000 / 60 / 60 / 24, 10)); //计算剩余的天数
  var hours = checkTime(parseInt((leftTime / 1000 / 60 / 60) % 24, 10)); //计算剩余的小时
  var minutes = checkTime(parseInt((leftTime / 1000 / 60) % 60, 10)); //计算剩余的分钟
  var seconds = checkTime(parseInt((leftTime / 1000) % 60, 10)); //计算剩余的秒数
  return {
    days,
    hours,
    minutes,
    seconds
  };
};
export default {
  props: {
    format: {
      type: String,
      default: "hh:mm:ss"
    },
    //倒计时剩余时间戳（ms）
    offset: {
      type: Number,
      default: 0
    },
    //是否启动热更新（自动计算倒计时）
    hotUpdate: {
      type: Boolean,
      default: true
    }
  },
  name: "count-down",
  data() {
    return {
      in_offset: 0,
      inter: null
    };
  },
  computed: {
    views() {
      let obj = gettime(this.in_offset);
      return this.format
        .replace("dd", obj.days)
        .replace("hh", obj.hours)
        .replace("mm", obj.minutes)
        .replace("ss", obj.seconds)
        .split("");
    }
  },
  watch: {
    offset: {
      immediate: true,
      handler(vel) {
        this.in_offset = vel;
        this.clear();
        this.start();
      }
    }
  },
  methods: {
    start() {
      if (this.in_offset > 0 && this.hotUpdate) {
        this.inter = new SetInterval(() => {
          this.in_offset -= 1000;
          let time = checkTime(parseInt(this.in_offset / 1000, 10));

          this.$emit("timeout", time);
          if (Number(time) == 0) {
            this.inter.$clear();
            setTimeout(() => {
              this.$emit("timeover");
            }, 1000);
          }
        }, 1000);
      }
    },
    clear() {
      this.inter && this.inter.$clear();
    }
  }
};
</script>

<style scoped lang="less"></style>
